﻿namespace SharePointService
{
    using System;
    using System.ServiceModel;
    using System.Xml;
    using System.Xml.Linq;

    using com.crownpack.probeservice;
    using com.crownpack.probeservice.Service_Lists;

    public class Lists : IDisposable
    {
        #region Fields

        bool disposed;
        ListsSoapClient _proxy;

        #endregion Fields

        #region Constructors

        ~Lists( )
        {
            proxy = null;
        }

        #endregion Constructors

        #region Properties

        public Uri HostEndpointAddressUri
        {
            get
            {
                return new Uri( string.Format( "{0}://{1}", proxy.Endpoint.Address.Uri.Scheme, proxy.Endpoint.Address.Uri.Host ) );
            }
        }

        ListsSoapClient proxy
        {
            get
            {
                if ( _proxy == null )
                {
                    _proxy = new ListsSoapClient( );
                    _proxy.ClientCredentials.UserName.UserName = _proxy.ClientCredentials.Windows.ClientCredential.UserName;
                    _proxy.ClientCredentials.UserName.Password = _proxy.ClientCredentials.Windows.ClientCredential.Password;
                    _proxy.ClientCredentials.Windows.AllowNtlm = true;
                }
                return _proxy;
            }
            set
            {
                if ( value == null && _proxy != null &&
                    ( _proxy.State == CommunicationState.Opened ||
                    _proxy.State == CommunicationState.Opening ) )
                    _proxy.Close( );
                _proxy = null;
            }
        }

        #endregion Properties

        #region Methods

        public XElement BuildOrderByElement( )
        {
            return BuildOrderByElement( string.Empty );
        }

        public XElement BuildOrderByElement( string orderby )
        {
            const string OrderBy = "OrderBy";
            if ( string.IsNullOrEmpty( orderby ) )
                return new XElement( OrderBy );
            return new XElement( OrderBy, XElement.Parse( orderby ) );
        }

        public XElement BuildOrderByElement( string orderby, params object[ ] args )
        {
            return BuildOrderByElement( string.Format( orderby, args ) );
        }

        public XElement BuildOrElement( string or, params object[ ] args )
        {
            const string Or = "Or";
            return new XElement( Or, string.Format( or, args ) );
        }

        public XElement BuildQueryElement( XElement orderByElement, string camlQuery, params object[ ] args )
        {
            return BuildQueryElement( orderByElement, string.Format( camlQuery, args ) );
        }

        public XElement BuildQueryElement( string camlQuery, params object[ ] args )
        {
            return BuildQueryElement( BuildOrderByElement( ), camlQuery, args );
        }

        public XElement BuildQueryElement( string camlQuery )
        {
            return BuildQueryElement( BuildOrderByElement( ), camlQuery );
        }

        public XElement BuildQueryElement( XElement orderByElement, string camlQuery )
        {
            const string Query = "Query";
            if ( string.IsNullOrEmpty( camlQuery ) )
                return new XElement( Query, orderByElement );
            return new XElement( Query, XElement.Parse( camlQuery ), orderByElement );
        }

        /// <summary>
        /// This IDisposable implementation follows Microsoft coding best practices.
        /// Dispose may also initiated by the destructor of this class.
        /// Performs tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// Because the Dispose is implemented, this class can be used in a 'using' statement.
        /// Do not make this method virtual. A derived class should not be able to override this method.
        /// Note: Within the destructor use Dispose(false). 
        /// </summary>
        public void Dispose( )
        {
            Dispose( true );
            // This object will be cleaned up by the Dispose method.
            // Therefore, call GC.SuppressFinalize to take this object off the finalization queue
            // and prevent finalization code for this object from executing a second time.
            GC.SuppressFinalize( this );
        }

        public void GetList( string listName )
        {
            GetListRequestBody body = new GetListRequestBody( listName );
            GetListRequest request = new GetListRequest( );
            GetListResponse response = proxy.GetList( request );
        }

        public XElement GetListItem( string listName, XElement query )
        {
            GetListItemsRequestBody body = new GetListItemsRequestBody( );
            body.listName = listName;
            body.query = query;
            GetListItemsRequest request = new GetListItemsRequest( body );
            GetListItemsResponse response = proxy.GetListItems( request );
            return response.Body.GetListItemsResult;
        }

        public void GetLists( )
        {
            GetListCollectionRequestBody body = new GetListCollectionRequestBody( );
            GetListCollectionRequest request = new GetListCollectionRequest( body );
            GetListCollectionResponse response = proxy.GetListCollection( request );
        }

        /// <summary>
        /// TODO: Convert to extension method
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        public XElement ToXElement( XmlNode node )
        {
            XDocument d = new XDocument( );
            using ( XmlWriter w = d.CreateWriter( ) )
                node.WriteTo( w );
            return d.Root;
        }

        public XmlNode ToXmlNode( XElement element )
        {
            using ( XmlReader xmlReader = element.CreateReader( ) )
            {
                XmlDocument xmlDoc = new XmlDocument( );
                xmlDoc.Load( xmlReader );
                return xmlDoc;
            }
        }

        // Dispose(bool disposing) executes in two distinct scenarios.
        // If disposing equals true, the method has been called directly
        // or indirectly by a user's code. Managed and unmanaged resources
        // can be disposed.
        // If disposing equals false, the method has been called by the
        // runtime from inside the finalizer and you should not reference
        // other objects. Only unmanaged resources can be disposed.
        void Dispose( bool disposing )
        {
            // check to see if Dispose has already been called.
            if ( !this.disposed )
            {
                // if displosing equals true, dispose all managed and unmanaged resources
                if ( disposing )
                {
                    // clear managed resources
                    proxy = null;
                }
                disposed = true;
            }
        }

        #endregion Methods
    }
}